﻿// GoodsBuyAndSale.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


#include <iostream>
#include<cstdlib>
using namespace std;

class Goods
{
public:


	Goods() {
		goodsWeightPer = 0; //每个货物的重量【这是每个对象的属性】
		next = NULL;
		//加一句调皮语
		cout << "此时对象的无参构造方法被调用，或者说对象的无参构造器被触发，一个重量为" << goodsWeightPer << "的货物被创建" << endl;
	}
	Goods(int w) {
		//调用有参构造，就是创建一个重量为w的货物，并且在仓库（就是那个链表中）添加这个货物【添加这个重量到链表后，类似于把这个货物加入到了仓库】，不就是totaiWeight += w;嘛
		goodsWeightPer = w;
		next = NULL;//保证next指针是一个合法值
		totalWeight += w;
		cout << "Goods的有参构造函数被触发，创建了一个重量为" << goodsWeightPer << "的货物" << endl;
	}

	~Goods()
	{
		//在析构函数中要做的事就是，当这个对象被调用时干掉这个类的totalWeight，链表减少这个货物的重量【相当于仓库增加删除了这个货物】
		cout << "删除了一箱重量是" << goodsWeightPer << "的货物" << endl;
		totalWeight -= goodsWeightPer;
	}

	Goods* next;

	//提供一个静态成员的访问接口,就是害怕有人要访问咱们这个静态成员变量totalWeight
	static int get_total_weight() {
		return totalWeight;
	}

private:
	int goodsWeightPer; //每个货物的重量
	static int totalWeight; //仓库的总重量
};

int Goods::totalWeight = 0;

/*
	 *  购买货物的方法
	 * head代表咱们用来装货物的链表 w代表这个货物的重量
	 * 咱们定义的代表仓库的链表头指针head，需要在buy()和sale()方法中进行改变，来代表货物被买入卖出。那么需要在buy()和sale()方法中使用二级指针或者引用方法将head传进去【想通过函数内部的东西来改变函数外部的值，就是下面两个方法，双*或者*&，当然啦，通过函数里面改变外边的一级指针，那么函数形参就得二级指针，那要通过函数里面改变外边的二级指针，那么函数形参就得三级指针】
	 * 第一种写法：使用二级指针：buy(Goods **head_p)通过传进来的head地址改变head指针方向及head内容
	 * 第二种写法：传入Goods引用head：buy(Goods * &head)，定义一个指向指针head的引用，*head不就代表head是一个指针嘛，那么定义一个指向指针的引用不就是* &head嘛。此时通过引用传递进来的就是你外边那个head，
	 */
void buy(Goods*& head, int w) {
	//主要业务逻辑就是判断形参传进来的东西合不合法，然后再展开业务逻辑
	Goods* newGoods = new Goods(w);//创建一个新货物，与此同时totalWeight要+1
	if (head == NULL)
	{
		head = newGoods;
	}
	else {
		//此时head不为空，证明head链表这个仓库中已经有货物了。所以按照咱们给链表中增加新节点的算法，不就是要插入的新货物(的next)指向head，然后head（的next指针）再指向新货物呗
		newGoods->next = head;
		head->next = newGoods;//把创建的新货物存到链表中
	}
}

/*
 * 售卖货物的方法
 * 咱们定义的代表仓库的链表头指针head，需要在buy()和sale()方法中进行改变，来代表货物被买入卖出。那么需要在buy()和sale()方法中使用二级指针或者引用方法将head传进去
 * 第一种写法：使用二级指针：buy(Goods **head_p)通过传进来的head地址改变head指针方向及head内容
 * 第二种写法：传入Goods引用head：buy(Goods * &head)
 */
void sale(Goods*& head) {
	if (head == NULL)
	{
		cout << "仓库中已经没有货物了" << endl;
		return;
	}
	//直接删除头指针中的节点，这个节点有自己对应的货物重量，delete这个节点代替删除节点中对应重量的货物即可
	
	Goods *temp = head;
	head = head->next;
	delete temp;

	/*
	 * 另一种写法，删除链表中某个节点,定义一个中间指针temp，然后让head直接指向head.next.next，head.next不就落单了嘛，然后可以用delete删除中间指针temp并触发析构函数
	 * Goods *temp = head;
	 * head = head.next;
	 * delete temp;
	 * 
	 * 
	 * 咱们在java中的思路就是head->next = head->next->next;
	 * head->next = NULL;
	 */
	cout << "货物已被卖出，saled" << endl;
}

int main()
{

	//定义存贮货物的仓库【就是那个链表的head】
	Goods* next;

	//用户做的选择：1买入货物、2卖出货物、0退出买卖界面
	int choice = 0;
	Goods* head = NULL;
	int createWeight;
	do
	{
		cout << "1: 买入货物" << endl;
		cout << "2: 卖出货物" << endl;
		cout << "0: 退出买卖界面" << endl;

		cin >> choice;
		switch (choice)
		{
		case 1:
			//代表进货
			cout << "请输入要创建的货物的重量" << endl;
			cin >> createWeight;
			buy(head, createWeight);
			break;
		case 2:
			//代表出货
			sale(head);
			break;
		case 0:
			//代表退出买卖界面
			return 0;
		default:
			break;
		}

		cout << "当前仓库的总重量是" << Goods::get_total_weight() << endl;

	} while (true);
	return 0;
}

